package libaudit

import (
	"encoding/json"
	"io/ioutil"
	"log"
	"os"

	"github.com/mozilla/libaudit-go"
)

func auditProc(e *libaudit.AuditEvent, err error) {
	if err != nil {
		// 查看错误是否为libaudit.ErrorAuditParse，如果是，则转换并同时显示
		// 我们无法分析的审计记录
		if nerr, ok := err.(libaudit.ErrorAuditParse); ok {
			log.Printf("解析器错误: %v: %v\n", nerr, nerr.Raw)
		} else {
			log.Printf("收到回调错误: %v\n", err)
		}
		return
	}
	// 将事件编组到JSON并打印
	buf, err := json.Marshal(e)
	if err != nil {
		log.Printf("回调无法发送事件: %v\n", err)
		return
	}
	log.Printf("%v\n", string(buf))
}

func Aduit_new() {
	s, err := libaudit.NewNetlinkConnection()
	if err != nil {
		log.Printf("NetNetlink连接: %v\n", err)
		os.Exit(1)
	}

	// if len(os.Args) != 2 {
	// 	fmt.Printf("使用: %v 到rules.json的路径\n", os.Args[0])
	// 	os.Exit(0)
	// }
	// 在内核中启用或禁用审核
	err = libaudit.AuditSetEnabled(s, true)
	if err != nil {
		log.Printf("已启用审计设置: %v\n", err)
		os.Exit(1)
	}
	// 设置内核中审计守护程序的 PID
	err = libaudit.AuditSetPID(s, os.Getpid())
	if err != nil {
		log.Printf("审核设置Pid: %v\n", err)
		os.Exit(1)
	}
	// 设置来自内核的审核消息的速率限制
	err = libaudit.AuditSetRateLimit(s, 1000)
	if err != nil {
		log.Printf("AuditSetRateLimit: %v\n", err)
		os.Exit(1)
	}
	// 设置内核中审核消息的积压工作限制
	err = libaudit.AuditSetBacklogLimit(s, 250)
	if err != nil {
		log.Printf("AuditSetBacklogLimit: %v\n", err)
		os.Exit(1)
	}

	var ar libaudit.AuditRules
	buf, err := ioutil.ReadFile("./audit_rules.json")
	if err != nil {
		log.Printf("读文件: %v\n", err)
	}
	// 确保我们可以解组规则JSON以验证它是正确的
	err = json.Unmarshal(buf, &ar)
	if err != nil {
		log.Printf("解组规则JSON: %v\n", err)
		os.Exit(1)
	}
	// DeleteAllRules删除审核系统中当前使用的所有审核规则
	// err = libaudit.DeleteAllRules(s)
	// if err != nil {
	// 	log.Printf("删除所有规则: %v\n", err)
	// 	os.Exit(1)
	// }
	log.Println(string(buf))
	// 添加规则集
	warnings, err := libaudit.SetRules(s, buf)
	if err != nil {
		log.Printf("SetRules: %v\n", err)
		os.Exit(1)
	}

	// 打印我们收到的所有警告，但仍会继续
	for _, x := range warnings {
		log.Printf("规则集警告: %v\n", x)
	}

	doneCh := make(chan bool, 1)
	libaudit.GetAuditMessages(s, auditProc, &doneCh)
}
